// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#ifndef MGCVETTABLE_H
#define MGCVETTABLE_H

#include <iostream>
#include "MgcTList.h"

using namespace std;

class MgcVetTable
{
public:
    // construction and destruction
    MgcVetTable ();
    ~MgcVetTable ();

    // forward reference
    class Edge;
    class Triangle;

    class Vertex
    {
    public:
        Vertex (unsigned int uiV);
        ~Vertex ();

        unsigned int m_uiV;

        MgcTList<Edge*> m_kEList;
        void AddEdge (Edge* pkEdge);

        MgcTList<Triangle*> m_kTList;
        void AddTriangle (Triangle* pkTriangle);
    };

    class Edge
    {
    public:
        Edge (unsigned int uiV0, unsigned int uiV1, Vertex* pkV0,
            Vertex* pkV1);
        ~Edge ();

        unsigned int m_auiV[2];
        Vertex* m_apkV[2];

        MgcTList<Triangle*> m_kTList;
        void AddTriangle (Triangle* pkTriangle);
    };

    class Triangle
    {
    public:
        Triangle (unsigned int uiT, unsigned int uiV0, unsigned int uiV1,
            unsigned int uiV2, Vertex* pkV0, Vertex* pkV1, Vertex* pkV2,
            Edge* pkE0, Edge* pkE1, Edge* pkE2);

        unsigned int m_uiT;

        unsigned int m_auiV[3];
        Vertex* m_apkV[3];

        Edge* m_apkE[3];
    };

    // return value is the added triangle
    Triangle* AddTriangle (unsigned int uiT, unsigned int uiV0,
        unsigned int uiV1, unsigned int uiV2);

    // return value is less than MAX_UNSIGNED_INT iff the triangle existed
    // and was removed
    unsigned int RemoveTriangle (unsigned int uiV0, unsigned int uiV1,
        unsigned int uiV2);

    // return value is true iff the edge existed and was collapsed
    bool CollapseEdge (unsigned int uiVKeep, unsigned int uiVThrow);

    // Items modified/deleted by a table modification call.  The lists are
    // reset at the beginning of the calls and added to during the calls, so
    // the application should check the lists *after* the calls. 
    MgcTList<unsigned int>& GetVertexDeleteList ();
    MgcTList<unsigned int>& GetTriangleDeleteList ();
    MgcTList<unsigned int>& GetTriangleModifiedList ();

    // vertex access
    MgcTList<Vertex*>& GetVertexList ();
    Vertex* GetVertex (unsigned int uiV);

    // edge access
    MgcTList<Edge*>& GetEdgeList ();
    Edge* GetEdge (unsigned int uiV0, unsigned int uiV1);

    // triangle access
    MgcTList<Triangle*>& GetTriangleList ();
    Triangle* GetTriangle (unsigned int uiV0, unsigned int uiV1,
        unsigned int uiV2);

    // readability
    void Print (ostream& rkOstr);

protected:
    // vertex data
    MgcTList<Vertex*> m_kVList;

    // edge data
    MgcTList<Edge*> m_kEList;

    // triangle data
    MgcTList<Triangle*> m_kTList;
    void DeleteTriangle (Triangle* pkTriangle);

    // items modified/deleted on a table modification call
    MgcTList<unsigned int> m_kVDeleteList;
    MgcTList<unsigned int> m_kTDeleteList;
    MgcTList<unsigned int> m_kTModifiedList;
};

#include "MgcVetTable.inl"

#endif
